const { menu } = require('../../models/system/menu');
const { buildTree } = require("../../utils/utils");
const logger = require('../../utils/logger');

class MenuService {
    static async addButtonRole(menuId, buttonData) {
        try {
            if (!menuId || !buttonData) {
                throw new Error('菜单ID和按钮数据不能为空');
            }
            
            const result = await menu.findOneAndUpdate(
                { _id: menuId },
                { $push: { btnRoles: buttonData } },
                { new: true }
            );
            
            if (!result) {
                throw new Error('菜单不存在');
            }
            
            logger.info(`成功为菜单添加按钮角色: ${menuId}`);
            return result;
        } catch (error) {
            logger.error(`添加按钮角色失败: ${error.message}, 菜单ID: ${menuId}`);
            throw new Error(`添加按钮角色失败: ${error.message}`);
        }
    }

    static async getButtonRoles(menuId) {
        try {
            if (!menuId) {
                throw new Error('菜单ID不能为空');
            }
            
            const result = await menu.findOne({ _id: menuId }).select('btnRoles -_id').lean();
            
            if (!result) {
                throw new Error('菜单不存在');
            }
            
            return result;
        } catch (error) {
            logger.error(`获取按钮角色失败: ${error.message}, 菜单ID: ${menuId}`);
            throw new Error(`获取按钮角色失败: ${error.message}`);
        }
    }

    static async updateButtonRole(menuId, buttonId, buttonData) {
        try {
            if (!menuId || !buttonId || !buttonData) {
                throw new Error('菜单ID、按钮ID和按钮数据不能为空');
            }
            
            const result = await menu.updateOne(
                { _id: menuId },
                { $set: { "btnRoles.$[element]": buttonData } },
                { arrayFilters: [{ "element._id": buttonId }], new: true }
            );
            
            if (result.modifiedCount === 0) {
                throw new Error('更新按钮角色失败，可能菜单或按钮不存在');
            }
            
            logger.info(`成功更新菜单按钮角色: ${menuId}, 按钮ID: ${buttonId}`);
            return result;
        } catch (error) {
            logger.error(`更新按钮角色失败: ${error.message}, 菜单ID: ${menuId}, 按钮ID: ${buttonId}`);
            throw new Error(`更新按钮角色失败: ${error.message}`);
        }
    }

    static async deleteButtonRole(menuId, buttonId) {
        try {
            if (!menuId || !buttonId) {
                throw new Error('菜单ID和按钮ID不能为空');
            }
            
            const result = await menu.findOneAndUpdate(
                { _id: menuId },
                { $pull: { btnRoles: { _id: buttonId } } },
                { new: true }
            );
            
            if (!result) {
                throw new Error('菜单不存在');
            }
            
            logger.info(`成功删除菜单按钮角色: ${menuId}, 按钮ID: ${buttonId}`);
            return result;
        } catch (error) {
            logger.error(`删除按钮角色失败: ${error.message}, 菜单ID: ${menuId}, 按钮ID: ${buttonId}`);
            throw new Error(`删除按钮角色失败: ${error.message}`);
        }
    }

    static async createMenu(menuData) {
        try {
            if (!menuData) {
                throw new Error('菜单数据不能为空');
            }
            
            // 数据验证
            if (!menuData.name) {
                throw new Error('菜单名称不能为空');
            }
            
            // 处理 parentId 和 isMenu 字段
            menuData.parentId = menuData.pid || '0';
            menuData.isMenu = menuData.ism !== undefined ? menuData.ism : true; // 默认为true
            
            // 验证父级菜单是否存在（如果不是根菜单）
            if (menuData.parentId !== '0') {
                const parentMenu = await menu.findOne({ _id: menuData.parentId });
                if (!parentMenu) {
                    throw new Error('父级菜单不存在');
                }
            }
            
            const result = await menu.create(menuData);
            logger.info(`成功创建菜单: ${result._id}`);
            return result;
        } catch (error) {
            logger.error(`创建菜单失败: ${error.message}`);
            throw new Error(`创建菜单失败: ${error.message}`);
        }
    }

    static async updateMenu(menuId, menuData) {
        try {
            if (!menuId || !menuData) {
                throw new Error('菜单ID和菜单数据不能为空');
            }
            
            // 数据验证
            if (menuData.name !== undefined && !menuData.name) {
                throw new Error('菜单名称不能为空');
            }
            
            // 处理 parentId 和 isMenu 字段
            if (menuData.pid !== undefined) {
                menuData.parentId = menuData.pid || '0';
            }
            if (menuData.ism !== undefined) {
                menuData.isMenu = menuData.ism;
            }
            
            // 验证父级菜单是否存在（如果不是根菜单且parentId被修改）
            if (menuData.parentId && menuData.parentId !== '0') {
                const parentMenu = await menu.findOne({ _id: menuData.parentId });
                if (!parentMenu) {
                    throw new Error('父级菜单不存在');
                }
            }
            
            const result = await menu.findOneAndUpdate(
                { _id: menuId },
                { $set: menuData },
                { new: true, runValidators: true }
            );
            
            if (!result) {
                throw new Error('菜单不存在');
            }
            
            logger.info(`成功更新菜单: ${menuId}`);
            return result;
        } catch (error) {
            logger.error(`更新菜单失败: ${error.message}, 菜单ID: ${menuId}`);
            throw new Error(`更新菜单失败: ${error.message}`);
        }
    }

    static async getMenuById(menuId) {
        try {
            if (!menuId) {
                throw new Error('菜单ID不能为空');
            }
            
            const result = await menu.findOne({ _id: menuId }).lean();
            
            if (!result) {
                throw new Error('菜单不存在');
            }
            
            return result;
        } catch (error) {
            logger.error(`获取菜单失败: ${error.message}, 菜单ID: ${menuId}`);
            throw new Error(`获取菜单失败: ${error.message}`);
        }
    }

    static async getMenuList() {
        try {
            const menus = await menu.find().lean();
            const tree = buildTree(menus);
            logger.info(`成功获取菜单列表，共${tree.length}个根菜单`);
            return tree;
        } catch (error) {
            logger.error(`获取菜单列表失败: ${error.message}`);
            throw new Error(`获取菜单列表失败: ${error.message}`);
        }
    }

    static async deleteMenu(menuId) {
        try {
            if (!menuId) {
                throw new Error('菜单ID不能为空');
            }
            
            // 使用事务确保数据一致性
            const session = await menu.startSession();
            session.startTransaction();
            
            try {
                // 先查找要删除的菜单
                const menuToDelete = await menu.findOne({ _id: menuId }).session(session);
                if (!menuToDelete) {
                    throw new Error('菜单不存在');
                }
                
                // 递归查找所有子菜单（包括子菜单的子菜单）
                const getAllSubMenus = async (parentId) => {
                    const directSubMenus = await menu.find({ parentId: parentId }).session(session);
                    let allSubMenus = [...directSubMenus];
                    
                    // 递归获取所有层级的子菜单
                    for (const subMenu of directSubMenus) {
                        const nestedSubMenus = await getAllSubMenus(subMenu._id);
                        allSubMenus = allSubMenus.concat(nestedSubMenus);
                    }
                    
                    return allSubMenus;
                };
                
                // 获取所有子菜单
                const allSubMenus = await getAllSubMenus(menuId);
                
                // 收集所有要删除的菜单ID（包括主菜单和所有子菜单）
                const menuIdsToDelete = [menuId, ...allSubMenus.map(m => m._id)];
                
                // 删除所有相关菜单
                const deleteResult = await menu.deleteMany({
                    _id: { $in: menuIdsToDelete }
                }).session(session);
                
                // 提交事务
                await session.commitTransaction();
                
                logger.info(`成功删除菜单及其${allSubMenus.length}个子菜单, 总计删除${deleteResult.deletedCount}个菜单`);
                return {
                    deletedCount: deleteResult.deletedCount,
                    menuIds: menuIdsToDelete
                };
            } catch (error) {
                // 回滚事务
                await session.abortTransaction();
                throw error;
            } finally {
                // 结束会话
                await session.endSession();
            }
        } catch (error) {
            logger.error(`删除菜单失败: ${error.message}, 菜单ID: ${menuId}`);
            throw new Error(`删除菜单失败: ${error.message}`);
        }
    }
}

module.exports = MenuService;
